Keyword
- Stacking Context(쌓임 맥락)
- React Portal
Contents
쌓임 맥락
3차원 개념화를 추가하기 위해서 Z축을 사용하는 방식이다. 각각의 DOM Element는 css 우선순위를 사용해서 3차원 공간을 차지한다.
규칙
- 쌓임 맥락 안의 자식요소는 쌓임 맥락 규칙과 동일하게 쌓인다.
- 자식의 z-index는 부모 요소에게만 의미가 있다.
- 쌓임 맥락은 다른 쌓임 맥락을 포함할 수 있고, 계층 구조를 이룬다.
- 형제 쌓임 맥락과 분리된다. 쌓임 맥락은 자손 요소만 고려한다.
ex)
- root
- DIV #1
- DIV #2
- DIV #3
- DIV #4
- DIV #5
- DIV #6
쌓임 순서
요소들의 쌓임 순서를 다르게 하기 위해서 두가지 조건이 필요하다.
- position 변경
- z-index 설정
z-index가 없을 경우의 쌓임
순서대로 아래에서 위로 쌓인다.
- root 요소의 배경과 테두리
- 자식 요소들은 DOM 순서대로.
- position이 설정된 자식 요소들은 DOM 순서대로
- position 속성 값과는 상관 없이 HTML 구조 순서대로 쌓인다.
- position이 설정되지 않은 요소는 항상 position이 설정된 요소 이전에 렌더링된다.
z-index 적용할 경우의 쌓임
먼저 요소에 position 속성을 지정하고 z-index를 설정해야한다.
- 같은 z-index를 가진다면 z-index가 없을 경우의 쌓임으로 규칙이 적용된다.
Rules
- 쌓임 맥락 안의 자식요소는 쌓임 맥락 규칙과 동일하게 쌓인다.
- 자식의 z-index는 부모 요소에게만 의미가 있다.
- 쌓임 맥락은 다른 쌓임 맥락을 포함할 수 있고, 계층 구조를 이룬다.
- 형제 쌓임 맥락과 분리된다. 쌓임 맥락은 자손 요소만 고려한다.
ex)
- root
- DIV #1
- DIV #2
- DIV #3
- DIV #4
- DIV #5
- DIV #6
쌓임 순서
요소들의 쌓임 순서를 다르게 하기 위해서 두가지 조건이 필요하다.
- position 변경
- z-index 설정
z-index가 없을 경우의 쌓임
순서대로 아래에서 위로 쌓인다.
- root 요소의 배경과 테두리
- 자식 요소들은 DOM 순서대로.
- position이 설정된 자식 요소들은 DOM 순서대로
- position 속성 값과는 상관 없이 HTML 구조 순서대로 쌓인다.
- position이 설정되지 않은 요소는 항상 position이 설정된 요소 이전에 렌더링된다.
z-index 적용할 경우의 쌓임
먼저 요소에 position 속성을 지정하고 z-index를 설정해야한다.
- 같은 z-index를 가진다면 z-index가 없을 경우의 쌓임으로 규칙이 적용된다.
Portal
React가 Portal로 해결하고자 했던 문제를 아래와 같은 구현 예제로 설명함
- 상단에 sticky한 네비게이션
- 접히는 사이드바
- 모달
-
모달을 바닐라 js로 구현할 때, 쌓임 맥락을 피하기 위해서는 아래와 같이 작성할 수 있다.
- body 태그 아래에 추가
- 구현 코드
- header - sticky
- layout
- sidebar - relative
- main
- modal - absolute
위 코드에서 header는 sticky에 z-index를 높여주면 원하는대로 상단에 고정되도록 구현할 수 있다. 하지만 모달이 main안에서 context가 존재하기 때문에 sidebar에 움직임에 따라서 shift가 발생할 뿐만 아니라 header에 가려지게된다. 이러한 문제를 해결하기 위해서 모달은
createPortal
과 함께 root 요소로 보낸다면 sidebar나 header에 영향없이 가장 상단 레이어에 위치시킬 수 있다. 실제 서비스를 구현하는 과정에서는 쌓임 맥락을 벗어날 수 없을 정도로 컴포넌트가 깊게 위치할 수 있기 때문에portal
을 사용함으로써 간단하게 원하는 레이어에 요소를 위치시킬 수 있다.
Portal 특징?
DOM 트리가 아니라 React 트리를 따른다.
- portal을 사용하는 컴포넌트의 context를 이용한다. 예를 들어서 main 컴포넌트 내부에서 portal을 사용해서 모달을 띄웠다면, main 컴포넌트가 unmount되면 모달도 없어진다.
- portal을 사용한 곳에서 event 전파가 발생한다. 모달에서 발생한 click 이벤트를 main 컴포넌트에서 잡을 수 있다.
CSS, Form Submit Event는 안된다.
- 렌더 트리를 생성하면서 DOM 트리의 요소와 CSSOM를 매칭하는 과정을 거치게 되는데, 실제 DOM 트리에서 root에 위치하기 때문에 css적인 요소는 실제 DOM 순서로 생각해야된다.
- “*submit event is not managed by React"*라고 한다. click 이벤트와 달리 submit 이벤트는 실제 DOM 순서로 생각해야한다.
- body 태그 아래에 추가